package net.oschina.victor.service;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import net.oschina.victor.entity.Role;
import net.oschina.victor.entity.User;
import net.oschina.victor.repsotory.UserRepsotory;
import net.oschina.victor.util.PasswordHelper;

@Service
public class UserServiceImpl implements UserService {
	private PasswordHelper passwordHelper = new PasswordHelper();

	@Autowired
	private UserRepsotory userRepsotory;
	@Autowired
	private RoleService roleService;

	@Transactional
	@Override
	public void changePassword(Long userId, String newPassword) {
		User user = userRepsotory.findOne(userId);
		user.setPassword(newPassword);
		passwordHelper.encryptPassword(user);
		userRepsotory.save(user);
	}

	@Transactional
	@Override
	public void deleteUser(Long userId) {
		userRepsotory.delete(userId);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
	@Override
	public User findById(Long userId) {
		return userRepsotory.findOne(userId);
	}

	@Transactional
	@Override
	public User findByUsername(String username) throws Exception {
		Specification<User> spec = new Specification<User>() {
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				return cb.equal(root.get("username"), username);
			}
		};
		List<User> list = userRepsotory.findAll(spec);
		if (list.isEmpty())
			return null;
		for (User user : list) {
			System.out.println(user.getRoles());
		}
		return list.get(0);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
	@Override
	public Set<String> findPermissions(String username) throws Exception {
		User user = findByUsername(username);
		if (user == null) {
			return Collections.emptySet();
		}
		return roleService.findPermissions(user.getRoles());
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
	@Override
	public Set<String> findRoles(String username) throws Exception {
		User user = findByUsername(username);
		if (user == null) {
			return Collections.emptySet();
		}
		Set<String> roleIds = new HashSet<>();
		for (Role role : user.getRoles()) {
			roleIds.add(role.getRole());
		}
		return roleIds;
	}

	@Override
	@Transactional
	public void saveUser(User user) throws Exception {
		if (user.getId() == null) { // 新增用户
			Specification<User> spec = new Specification<User>() {
				@Override
				public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
					return cb.equal(root.get("username"), user.getUsername());
				}
			};
			List<User> list = userRepsotory.findAll(spec);
			if (list == null || list.isEmpty()) {
				userRepsotory.save(user); // 将数据保存
			} else {
				new Exception("用户名称出现重复!");
			}
		} else {
			Specification<User> spec = new Specification<User>() {
				@Override
				public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
					return cb.and(cb.notEqual(root.get("id"), user.getId()),
							cb.equal(root.get("username"), user.getUsername()));
				}
			};
			List<User> list = userRepsotory.findAll(spec);
			if (list == null || list.isEmpty()) {
				userRepsotory.save(user);
			} else {
				new Exception("用户名称与现有用户重复");
			}
		}
	}

}
